package com.hctg.forced2sleep.utils;

import android.accessibilityservice.AccessibilityService;
import android.app.Activity;
import android.app.Application;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ResolveInfo;
import android.graphics.Rect;
import android.os.Build;
import android.provider.Settings;
import android.text.TextUtils;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityWindowInfo;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.actor.myandroidframework.utils.ConfigUtils;
import com.actor.myandroidframework.utils.LogUtils;
import com.blankj.utilcode.util.GsonUtils;
import com.blankj.utilcode.util.Utils;

import java.io.File;
import java.util.List;

/**
 * Created by popfisher on 2017/7/11.
 * 使用本工具前需要先初始化{@link #updateEvent(AccessibilityService, AccessibilityEvent)}
 */

public class AccessibilityUtils {

    private static final Application app = Utils.getApp();
    private static AccessibilityService accessibilityService;
    //页面名称: Activity/Dialog 名称
//    private static String pageName;
    private static boolean startRecord = false;

    private AccessibilityUtils() {
        throw new RuntimeException(getClass().getName() + " can not be new!");
    }

    /**
     * 判断是否有辅助功能权限
     * @param service 无障碍服务
     */
    public static boolean isAccessibilitySettingsOn(Class<? extends AccessibilityService> service) {
        int accessibilityEnabled = 0;
        try {
            //if系统中查到有1个App有无障碍权限, 就会返回1
            accessibilityEnabled = Settings.Secure.getInt(app.getContentResolver(), Settings.Secure.ACCESSIBILITY_ENABLED);
        } catch (Settings.SettingNotFoundException e) {
            e.printStackTrace();
        }

        if (accessibilityEnabled == 1) {
            String packageName = app.getPackageName();
            //com.hctg.forced2sleep/com.hctg.forced2sleep.service.MyAccessibilityService
            String serviceStr = packageName + File.separator + service.getName();

            //返回系统中所有有无障碍权限的App信息
            //com.actor.develop_helper/com.actor.develop_helper.service.ViewPackageAndClassNameService:com.hctg.forced2sleep/com.hctg.forced2sleep.service.MyAccessibilityService
            String settingValues = Settings.Secure.getString(app.getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);

            if (settingValues != null) {
                TextUtils.SimpleStringSplitter stringSplitter = new TextUtils.SimpleStringSplitter(':');
                stringSplitter.setString(settingValues);
                while (stringSplitter.hasNext()) {
                    String accessibilityService = stringSplitter.next();
                    if (accessibilityService.equalsIgnoreCase(serviceStr)) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    /**
     * 跳转到系统无障碍设置页面
     * @param requestCode 请求码
     */
    public static void go2AccessibilitySetting(Activity activity, int requestCode) {
        Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
        activity.startActivityForResult(intent, requestCode);
    }

    // TODO: 2024/10/7 ??
    public static String n() {
        ActivityInfo activityInfo;
        ResolveInfo resolveActivity = ConfigUtils.APPLICATION.getPackageManager().resolveActivity(
                new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS), 0);
        if (resolveActivity == null || (activityInfo = resolveActivity.activityInfo) == null) {
            return null;
        }
        return activityInfo.packageName;
    }

    /**
     * 初始化/更新 service&event
     */
    public static void updateEvent(@NonNull AccessibilityService service, AccessibilityEvent event) {
        accessibilityService = service;
        if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
//            CharSequence className = event.getClassName();
//            if (className != null) {
//                String s = className.toString();
//                //音量开关: com.android.systemui.volume.VolumeDialogImpl$CustomDialog
//                if (s.contains("com.android.systemui.volume")) {
//                    return;
//                }
//                //FrameLayout, RelativeLayout
//                if (s.startsWith("android.widget")) {
//                    //页面名称: Activity/Dialog 名称
//                    pageName = s;
//                }
//            }
        }

        printAccessibilityEvent(event);
//        if (startRecord) {
//            findAllNodes("", event.getSource(), );
//        }
    }

    /**
     * 获取页面的所有window <br />
     * 普通手机: windows.size=4, 包括: 导航栏, 状态栏, App页面(不包含←这2个栏), 整个屏幕
     *
     * (vivo X27, android 10)手势侧滑, 拍照页面: windows.size=4, 包括: 导航栏, 右侧侧滑, 左侧侧滑, App整个屏幕         ↓(这是杠, 不是减号!)
     *      windows[0]=AccessibilityWindowInfo[title=null, id=106, type=TYPE_SYSTEM, layer=3, bounds=Rect(0, 2298 - 1080, 2340), focused=false, active=false, pictureInPicture=false, hasParent=false, isAnchored=false, hasChildren=false]
     *      windows[1]=AccessibilityWindowInfo[title=null, id=105, type=TYPE_SYSTEM, layer=2, bounds=Rect(1008, 84 - 1080, 2298), focused=false, active=false, pictureInPicture=false, hasParent=false, isAnchored=false, hasChildren=false]
     *      windows[2]=AccessibilityWindowInfo[title=null, id=101, type=TYPE_SYSTEM, layer=1, bounds=Rect(0, 84 - 72, 2298), focused=false, active=false, pictureInPicture=false, hasParent=false, isAnchored=false, hasChildren=false]
     *      windows[3]=AccessibilityWindowInfo[title=相机, id=120, type=TYPE_APPLICATION, layer=0, bounds=Rect(0, 0 - 1080, 2340), focused=true, active=true, pictureInPicture=false, hasParent=false, isAnchored=false, hasChildren=false]
     * (vivo X27, android 10)手势侧滑: windows.size=5, 包括: 导航栏, 右侧侧滑, 左侧侧滑, 状态栏, App整个屏幕
     *      windows[0]=AccessibilityWindowInfo[title=null, id=50, type=TYPE_SYSTEM, layer=4, bounds=Rect(0, 2298 - 1080, 2340), focused=false, active=false, pictureInPicture=false, hasParent=false, isAnchored=false, hasChildren=false]
     *      windows[1]=AccessibilityWindowInfo[title=null, id=49, type=TYPE_SYSTEM, layer=3, bounds=Rect(1008, 84 - 1080, 2298), focused=false, active=false, pictureInPicture=false, hasParent=false, isAnchored=false, hasChildren=false]
     *      windows[2]=AccessibilityWindowInfo[title=null, id=43, type=TYPE_SYSTEM, layer=2, bounds=Rect(0, 84 - 72, 2298), focused=false, active=false, pictureInPicture=false, hasParent=false, isAnchored=false, hasChildren=false]
     *      windows[3]=AccessibilityWindowInfo[title=null, id=45, type=TYPE_SYSTEM, layer=1, bounds=Rect(0, 0 - 1080, 84), focused=false, active=false, pictureInPicture=false, hasParent=false, isAnchored=false, hasChildren=false]
     *      windows[4]=AccessibilityWindowInfo[title=趣词, id=37, type=TYPE_APPLICATION, layer=0, bounds=Rect(0, 0 - 1080, 2340), focused=true, active=true, pictureInPicture=false, hasParent=false, isAnchored=false, hasChildren=false]
     * (vivo X27, android 10)手势侧滑: windows.size=6, 包括: 导航栏, 右侧侧滑, 左侧侧滑, 状态栏, 状态栏下区域, App整个屏幕
     *      windows[0]=AccessibilityWindowInfo[title=null, id=50, type=TYPE_SYSTEM, layer=5, bounds=Rect(0, 2298 - 1080, 2340), focused=false, active=false, pictureInPicture=false, hasParent=false, isAnchored=false, hasChildren=false]
     *      windows[1]=AccessibilityWindowInfo[title=null, id=49, type=TYPE_SYSTEM, layer=4, bounds=Rect(1008, 84 - 1080, 2298), focused=false, active=false, pictureInPicture=false, hasParent=false, isAnchored=false, hasChildren=false]
     *      windows[2]=AccessibilityWindowInfo[title=null, id=43, type=TYPE_SYSTEM, layer=3, bounds=Rect(0, 84 - 72, 2298), focused=false, active=false, pictureInPicture=false, hasParent=false, isAnchored=false, hasChildren=false]
     *      windows[3]=AccessibilityWindowInfo[title=null, id=45, type=TYPE_SYSTEM, layer=2, bounds=Rect(0, 0 - 1080, 84), focused=false, active=false, pictureInPicture=false, hasParent=false, isAnchored=false, hasChildren=false]
     *      windows[4]=AccessibilityWindowInfo[title=null, id=60, type=TYPE_SYSTEM, layer=1, bounds=Rect(0, 84 - 1080, 2340), focused=false, active=false, pictureInPicture=false, hasParent=false, isAnchored=false, hasChildren=false]
     *      windows[5]=AccessibilityWindowInfo[title=趣词, id=37, type=TYPE_APPLICATION, layer=0, bounds=Rect(0, 0 - 1080, 2340), focused=true, active=true, pictureInPicture=false, hasParent=false, isAnchored=false, hasChildren=false]
     *
     * (honor v30, android 12)手势侧滑: windows.size=6, 包括: 导航栏, 右侧侧滑, 左侧侧滑, 状态栏, 状态栏下区域, App整个屏幕
     * windows[0]=AccessibilityWindowInfo[title=GestureNavBottom, displayId=0, id=9971, type=TYPE_SYSTEM, layer=5, region=SkRegion((0,2280,120,2334)(960,2280,1080,2334)(0,2334,1080,2400)), bounds=Rect(0, 2280 - 1080, 2400), focused=false, active=false, pictureInPicture=false, hasParent=false, isAnchored=false, hasChildren=false]
     * windows[1]=AccessibilityWindowInfo[title=GestureNavRight, displayId=0, id=9965, type=TYPE_SYSTEM, layer=4, region=SkRegion((1032,600,1080,2400)), bounds=Rect(1032, 600 - 1080, 2400), focused=false, active=false, pictureInPicture=false, hasParent=false, isAnchored=false, hasChildren=false]
     * windows[2]=AccessibilityWindowInfo[title=GestureNavLeft, displayId=0, id=9972, type=TYPE_SYSTEM, layer=3, region=SkRegion((0,600,48,2400)), bounds=Rect(0, 600 - 48, 2400), focused=false, active=false, pictureInPicture=false, hasParent=false, isAnchored=false, hasChildren=false]
     * windows[3]=AccessibilityWindowInfo[title=null, displayId=0, id=9964, type=TYPE_SYSTEM, layer=2, region=SkRegion((0,0,1080,135)), bounds=Rect(0, 0 - 1080, 135), focused=false, active=false, pictureInPicture=false, hasParent=false, isAnchored=false, hasChildren=false]
     * windows[4]=AccessibilityWindowInfo[title=null, displayId=0, id=11268, type=TYPE_SYSTEM, layer=1, region=SkRegion((0,135,1080,2400)), bounds=Rect(0, 135 - 1080, 2400), focused=false, active=false, pictureInPicture=false, hasParent=false, isAnchored=false, hasChildren=false]
     * windows[5]=AccessibilityWindowInfo[title=趣词, displayId=0, id=11267, type=TYPE_APPLICATION, layer=0, region=SkRegion((0,0,1080,2400)), bounds=Rect(0, 0 - 1080, 2400), focused=true, active=true, pictureInPicture=false, hasParent=false, isAnchored=false, hasChildren=false]
     */
    @Nullable
    public static List<AccessibilityWindowInfo> getWindows() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && accessibilityService != null) {
            List<AccessibilityWindowInfo> windows = accessibilityService.getWindows();
            LogUtils.errorFormat("windows.size=%d", windows.size());
            if (ConfigUtils.IS_APP_DEBUG) {
                for (int i = 0; i < windows.size(); i++) {
                    AccessibilityWindowInfo windowInfo = windows.get(i);
                    LogUtils.errorFormat("windows[%d]=%s", i, windowInfo.toString());
                }
            }
            return windows;
        }
        return null;
    }

    /**
     * @return
     */
    @Nullable
    public static AccessibilityNodeInfo getRootNodeInfo() {
        List<AccessibilityWindowInfo> windows = getWindows();
        if (windows != null && windows.size() > 0) {
            return windows.get(windows.size() - 1).getRoot();
        }
        if (accessibilityService != null) {
            // getRootInActiveWindow，不依赖当前的事件类型
            return accessibilityService.getRootInActiveWindow();
        }
        /**
         * 下面这个必须依赖当前的AccessibilityEvent
         * 当有新页面的时候, if这个不是最新的页面, 调用会报错: Cannot perform this action on a not sealed instance.
         * @see android.view.accessibility.AccessibilityRecord#getSource() 里的第1行代码
         */
//        if (accessibilityEvent != null) return accessibilityEvent.getSource();
        return null;
    }

//    @NonNull
//    public static String getPageName() {
//        return pageName;
//    }

    /**
     * 查找所有子节点
     */
    @NonNull
    public static void findAllNodes(@NonNull AccessibilityNodeInfo rootNodeInfo,
                                    List<AccessibilityNodeInfo> list, boolean isContainViewGroup) {
//        LogUtils.errorFormat("view.id: %s", rootNodeInfo.getViewIdResourceName());
        if (isContainViewGroup) {
            list.add(rootNodeInfo);
        }
        for (int i = 0; i < rootNodeInfo.getChildCount(); i++) {
            AccessibilityNodeInfo child = rootNodeInfo.getChild(i);
            if (child == null) continue;
//            LogUtils.errorFormat("view.id: %s", child.getViewIdResourceName());
            CharSequence className = child.getClassName();
            if (className != null) {
                if (child.getChildCount() == 0) {
                    list.add(child);
                } else {
                    findAllNodes(child, list, isContainViewGroup);
                }
            }
        }
    }

    /**
     * 是否有状态栏
     * @return
     */
    public static boolean hasStatusBar() {
        //方法1: 在自己app可行, 别的app不行(2种方式获取的都不行)
//        List<AccessibilityNodeInfo> nodes = findNodesById("android:id/statusBarBackground");
//        if (nodes != null) {
//            for (int i = 0; i < nodes.size(); i++) {
//                AccessibilityNodeInfo accessibilityNodeInfo = nodes.get(i);
//                LogUtils.errorFormat("%d. accessibilityNodeInfo: %s", i, accessibilityNodeInfo);
//            }
//        }
//        return CollectionUtils.isNotEmpty(nodes);
        //方法2:
        List<AccessibilityWindowInfo> windows = getWindows();
        if (windows == null || windows.isEmpty()) return false;
        Rect rect = new Rect();
        for (AccessibilityWindowInfo win : windows) {
            win.getBoundsInScreen(rect);
//            LogUtils.errorFormat("rect.top=%d, rect.bottom=%d, STATUS_BAR_HEIGHT=%d", rect.top, rect.bottom, ConfigUtils.STATUS_BAR_HEIGHT);
            if (rect.top == 0 && rect.bottom == ConfigUtils.STATUS_BAR_HEIGHT) return true;
        }
        return false;
    }

    /**
     * 根据Text搜索所有符合条件的节点, 模糊搜索方式
     */
    public static List<AccessibilityNodeInfo> findNodesByText(String text) {
        AccessibilityNodeInfo nodeInfo = getRootNodeInfo();
        if (nodeInfo != null) {
           return nodeInfo.findAccessibilityNodeInfosByText(text);
        }
        return null;
    }

    /**
     * 根据View的ID搜索符合条件的节点,精确搜索方式;
     * 这个只适用于自己写的界面，因为ID可能重复
     * api要求18及以上
     * @param viewId 要加上包名,示例:com.google.example:id/cb_checkbox
     */
    public static List<AccessibilityNodeInfo> findNodesById(String viewId) {
        AccessibilityNodeInfo nodeInfo = getRootNodeInfo();
        if (nodeInfo != null) {
            if (Build.VERSION.SDK_INT >= 18) {
                return nodeInfo.findAccessibilityNodeInfosByViewId(viewId);
            }
        }
        return null;
    }

    public static boolean clickByText(String text) {
        return performClick(findNodesByText(text));
    }

    /**
     * 根据View的ID搜索符合条件的节点,精确搜索方式;
     * 这个只适用于自己写的界面，因为ID可能重复
     * api要求18及以上
     * @param viewId
     * @return 是否点击成功
     */
    public static boolean clickById(String viewId) {
        return performClick(findNodesById(viewId));
    }

    /**
     * 模拟点击
     */
    private static boolean performClick(List<AccessibilityNodeInfo> nodeInfos) {
        if (nodeInfos != null && !nodeInfos.isEmpty()) {
            for (AccessibilityNodeInfo node : nodeInfos) {
                // 获得点击View的类型
                LogUtils.errorFormat("View类型：%s", node.getClassName());
                // 进行模拟点击
                if (node.isEnabled()) {
                    return node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
                }
            }
        }
        return false;
    }

    /**
     * 模拟点击返回键
     */
    public static boolean clickBackKey() {
        return performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK);
    }

    /**
     * 模拟action所对应事件
     */
    private static boolean performGlobalAction(int action) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            return accessibilityService.performGlobalAction(action);
        }
        return false;
    }

    /**
     * @param event
     * {"mAction":0,"mContentChangeTypes":0,"mEventTime":337739412,"mEventType":2,
     * "mMovementGranularity":0,"mPackageName":"com.huawei.android.launcher","mRecords":null,
     * "mAddedCount":-1,"mBeforeText":null,"mBooleanProperties":514,
     * "mClassName":"android.widget.TextView",
     * "mConnectionId":2,"mContentDescription":null,"mCurrentItemIndex":-1,"mFromIndex":-1,
     * "mIsInPool":false,"mItemCount":-1,"mMaxScrollX":-1,"mMaxScrollY":-1,"mNext":null,
     * "mParcelableData":null,"mRemovedCount":-1,"mScrollX":-1,"mScrollY":-1,"mSealed":true,
     * "mSourceNode":{
     *      "mActions":[{"mActionId":1,"mLabel":null},{"mActionId":4,"mLabel":null},
     *                  {"mActionId":8,"mLabel":null},{"mActionId":16,"mLabel":null},
     *                  {"mActionId":32,"mLabel":null},{"mActionId":64,"mLabel":null},
     *                  {"mActionId":256,"mLabel":null},{"mActionId":512,"mLabel":null},
     *                  {"mActionId":131072,"mLabel":null},{"mActionId":16908342,"mLabel":null}
     *                 ],
     *      "mBooleanProperties":264420,
     *      "mBoundsInParent":{"bottom":184,"left":524226,"right":524366,"top":0},
     *      "mBoundsInScreen":{"bottom":424,"left":8,"right":148,"top":240},
     *      "mChildNodeIds":null,
     *      "mClassName":"android.widget.TextView",
     *      "mCollectionInfo":null,"mCollectionItemInfo":null,"mConnectionId":2,
     *      "mContentDescription":null,"mDrawingOrderInParent":6,"mError":null,
     *      "mExtraDataKeys":["android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_KEY"],
     *      "mExtras":null,"mHintText":null,"mInputType":0,"mLabelForId":9223372034707292159,
     *      "mLabeledById":9223372034707292159,"mLiveRegion":0,"mMaxTextLength":-1,
     *      "mMovementGranularities":31,"mOriginalText":null,
     *      "mPackageName":"com.huawei.android.launcher","mParentNodeId":-4294967292,
     *      "mRangeInfo":null,"mSealed":true,"mSourceNodeId":-4294967286,"mText":"强制早睡",
     *      "mTextSelectionEnd":-1,"mTextSelectionStart":-1,"mTraversalAfter":9223372034707292159,
     *      "mTraversalBefore":9223372034707292159,"mViewIdResourceName":null,"mWindowId":15
     *  },
     * "mSourceWindowId":15,"mText":["强制早睡"],"mToIndex":-1
     * }
     */
    public static void printAccessibilityEvent(AccessibilityEvent event) {
        if (ConfigUtils.IS_APP_DEBUG) {
            try {
                String json = GsonUtils.toJson(event);
                LogUtils.errorFormat("AccessibilityEvent = %s", json);
            } catch (IllegalArgumentException e) {
                /**
                 * java.lang.IllegalArgumentException:
                 * Class android.content.res.ColorStateList declares multiple JSON fields named 'mChangingConfigurations';
                 * conflict is caused by fields android.content.res.ColorStateList#mChangingConfigurations
                 * and android.content.res.ComplexColor#mChangingConfigurations
                 */
//                e.printStackTrace();
                LogUtils.error("打印AccessibilityEvent出错:", e);
            }
        }
    }
}
